home *** CD-ROM | disk | FTP | other *** search
- From: scott@zorch.UUCP (Scott Hazen Mueller)
- Newsgroups: comp.sources.misc
- Subject: v02i004: 3B1 status bar redux
- Message-ID: <7078@ncoast.UUCP>
- Date: 15 Jan 88 00:28:37 GMT
- Approved: allbery@ncoast.UUCP
-
- Comp.Sources.Misc: Volume 2, Issue 4
- Submitted-By: Scott Hazen Mueller <scott@zorch.uucp>
- Archive-Name: 3b1-status-line
-
- This is a considerable enhanced (enhacked?) version of the 3B1 status bar
- program that I posted to comp.sources.misc around last October. This version
- is not quite so minimal. In addition to displaying a status line across the
- top of the screen, it uses the Suspend and Resume keys to switch to the next
- and previous windows; combined with multiple console gettys it gives behavior
- rather like that of 80x86-based Unices with virtual consoles. Also, it maps
- a bunch of 'extended-status' functions to the shifted Function keys on the
- console keyboard (and a help function to shift-Print).
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # ReadMe
- # Makefile
- # newmgr.c
- # startmgr.c
- # ndir.c
- # ndir.h
- # This archive created: Sat Jan 9 21:15:14 1988
- export PATH; PATH=/bin:$PATH
- if test -f 'ReadMe'
- then
- echo shar: will not over-write existing file "'ReadMe'"
- else
- cat << \SHAR_EOF > 'ReadMe'
-
- ReadMe for 9 Jan 1988 version of startmgr and newmgr
-
- These two programs implement a replacement for smgr, wmgr and ph. They don't
- do the cron stuff; use cron for that. They don't do mail, and I don't care,
- because I don't use /bin/mail anyway. Likewise, they know nothing about
- calendars or memos. Additionally, the wmgr function doesn't bring up a menu;
- it just switches you between windows.
-
- What startmgr does is start newmgr. It starts it in a window across the
- top of the screen, in the places where the Phone Manager, the Status Manager
- and the Window Manager live (I don't use the PM either...). It then returns,
- so all you need to do is startmgr. It probably can be turned into a fairly
- general process starter, but I don't have the time, what with all of the
- stuff that I've got piled up to look at.
-
- Newmgr is just a forever loop that displays some status information to
- stdout and peeks at the Suspend, Resume Shift-Print and Shift-Function Keys.
- The Shift-Function keys display all sorts of additional status information;
- since I use UUCP a lot, four of the keys show UUCP-related information (LCK,
- C. and D. files and all of /usr/spool/uucp) and the other four show process
- status, utmp information, the mail directory, and root disk stats. Feel free
- to hack it; I just put up what I could think of that's interesting to me. Load
- averages would be nice, but I couldn't find any obvious hooks in /unix for that.
-
- Compiling: just type make. Use make install to move the executables to the
- default locations. Modify the Makefile and the #define BARPROG for your site.
- I use the ndir stuff (I got it from News, I don't know who did it originally)
- to do directory scanning; it should be in the distribution.
-
- How to use: startmgr goes in /etc/daemons and newmgr goes into your
- local executable directory (change a #define in startmgr if you don't
- use /usr/local). You've then either got to change /etc/rc (so it doesn't
- start smgr,wmgr and ph) or put a script in /etc/daemons to kill them off.
- If you don't know about /etc/rc and /etc/daemons, maybe you shouldn't
- be doing this... :-)
-
- Use the Shift-Print key to display the list of key mappings, once the program
- is started.
-
- Optionally, you *can* run startmgr by hand; I did for testing. The only
- thing to note here is that your current window winds up being the one
- that startmgr creates for the status line; I couldn't find a way to say,
- "make the last window the current one."; or at least, one that I could get
- to work in 5 minutes... To get back to your normal window, just use
- Suspend/Resume.
-
- Known bugs: Every once in a while, like if you log out *just* as the display
- is updating, it gets confused as to what window you're really in. It has even
- been known to display "w-1" (who me, check for errors on a system call?).
- Also, the process status feature probably could find a better way to determine
- a process's controlling terminal; it has a tendency to come up with things
- like /dev/null.
-
- Potential bugs: Pretty much all of the extended-status routines are
- implemented without any error-checking...
-
- Last note: this stuff is copyrighted with free redistribution permitted.
- I don't really think that this is the sort of thing that needs or warrants
- scads of support, so I'm not promising to do so; however, I would like to
- see any changes that anyone makes.
-
- Comments welcome, as long as they are other than, "What kind of idiot
- runs without smgr, wmgr and ph?"
-
- \scott
- 9 Jan 1988
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- LOCALDIR = /usr/local
-
- all: newmgr startmgr
-
- startmgr: startmgr.c
- cc -O -s startmgr.c -o startmgr
-
- newmgr: newmgr.o ndir.o
- cc -O -s newmgr.o ndir.o -o newmgr
-
- install: newmgr startmgr
- mv newmgr LOCALDIR
- mv startmgr /etc/daemons
-
- clean:
- rm -f *.o startmgr newmgr
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'newmgr.c'
- then
- echo shar: will not over-write existing file "'newmgr.c'"
- else
- cat << \SHAR_EOF > 'newmgr.c'
- /* newmgr: Loop forever, printing a status display and checking the
- Suspend, Resume and shifted Function Keys. Meant to be used on the
- top line of a Unix-PC (7300/3B1) screen that has had the Phone Manager,
- Status Manager and Window Manager disabled. What it shows:
-
- - Phone line states
- o Idle - completely free line
- o Ansr - computer answering line (getty job)
- o Mach - incoming machine
- o User - incoming user
- o Call - any outbound
- - Boot date and time
- - Current run level
- - Current date and time
- - Number of users
-
- When Suspend is hit, it makes the next window current; Resume
- makes the last window current.
-
- The following functions are mapped to the function keys:
-
- Shift-F1: process display, similar to 'ps -ef'
- Shift-F2: utmp display, like 'who'
- Shift-F3: lists UUCP LCK.. files, if any
- Shift-F4: directory of /usr/mail
- Shift-F5: Root filesystem freespace and free inodes
- Shift-F6: lists UUCP C. files, if any
- Shift-F7: lists UUCP X. files, if any
- Shift-F8: directory of /usr/spool/uucp
-
- This is started by startmgr (which should be included in any
- distribution) so that the fork/exec/open code doesn't have to be
- carried around with this program.
-
- The process table stuff is heavily inspired by the 'fuser.c' program
- posted to the Usenet by Michael 'Ford' Ditto.
-
- This software is Copyright (c) 1987 by Scott Hazen Mueller.
-
- Permission is hereby granted to copy, reproduce, redistribute or
- otherwise use this software as long as: there is no monetary
- profit gained specifically from the use or reproduction or this
- software, it is not sold, rented, traded or otherwise marketed, and
- this copyright notice is included prominently in any copy
- made.
-
- The author make no claims as to the fitness or correctness of
- this software for any use whatsoever, and it is provided as is.
- Any use of this software is at the user's own risk.
-
- (Copyright notice courtesy of News 2.11 :-)
-
- Additionally: you break it, you bought it. I've listed the problems
- that I know of in comments in the code; if you come up with fixes, I'd
- like to see them, but I'm not planning on supporting anything. It's
- "good enough"; that's all that I'm looking for. */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/phone.h>
- #include <sys/window.h>
- #include <sys/signal.h>
- #include <sys/filsys.h>
- #include <sys/proc.h>
- #include <sys/user.h>
- #include <sys/syslocal.h>
- #include <sys/tune.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
- #include <utmp.h>
- #include <nlist.h>
- #include <pwd.h>
- #include "ndir.h"
-
- #define PHONE1 "ph0"
- #define PHONE2 "ph1"
- #define IDLE 0
- #define ANSR 1
- #define MACH 2
- #define USER 3
- #define CALL 4
- #define BARFORM "%s1 %s2 | Up Since %s | %s | %s | %d Users | w%d \r"
- #define MACHLEN 15
- #define MAXPATHLEN 255
- #define LOCKDIR "/usr/spool/uucp/"
- #define MAILDIR "/usr/mail/"
- #define DEVDIR "/dev/"
- #define LOCKPREFIX "LCK.."
- #define COMPREFIX "C."
- #define UUXPREFIX "X."
- #define TRUE (1)
- #define FALSE (0)
- #define TIMEFORM "%.2d/%.2d %.2d:%.2d"
- #define TICK 15
- #define WHOSLEEP 15
- #define NOWHERE 0
- #define FORWARD 1
- #define BACKWARD 2
- #define HERE 3
- #define MINWIN 1
- #define MAXWIN 12
-
- char *phstat[5] = { "Idle", "Ansr", "Mach", "User", "Call" };
-
- main()
- {
- int nusers;
- char curtime[26], boottime[26], rl[12], line[80], *fmttime();
- struct utmp *ut, *getutent();
- long temp;
-
- /* Ignore keyboard interrupt signals. */
-
- signal( SIGINT, SIG_IGN );
- signal( SIGQUIT, SIG_IGN );
-
- /* Open up the utmp file and find the boot time; save for display. */
-
- while ( ( ut = getutent() ) != NULL )
- if ( (int) ut->ut_type == BOOT_TIME ) {
- strcpy( boottime, fmttime( localtime( &( ut->ut_time ) ) ) );
- break;
- }
- endutent();
-
- for (;;) {
-
- /* Scan the utmp file, noting the run level and totting up users. */
-
- nusers = 0;
- while ( ( ut = getutent() ) != NULL ) {
- switch ( (int) ut->ut_type ) {
- case USER_PROCESS : nusers++; break;
- case RUN_LVL : strcpy( rl, ut->ut_line ); break;
- default : break;
- }
- }
- endutent();
-
- /* Figure out the current time. Temp is needed 'cause localtime wants
- an address. */
-
- temp = time( (long *) 0 );
- strcpy( curtime, fmttime( localtime( &temp ) ) );
-
- /* Format and print. Flush stdout to make it really get printed. */
-
- sprintf( line, BARFORM, phstat[ phone_stat( PHONE1 ) ],
- phstat[ phone_stat( PHONE2 ) ], boottime, rl, curtime, nusers,
- curwinno() );
- printf( "%s", line );
- fflush( stdout );
-
- /* Take care of the window management stuff; also do some sleeping down
- there. */
-
- wcheckz();
- }
- }
-
- char *fmttime( tm )
-
- /* Format a time structure into a string the way *I* want it. */
-
- struct tm *tm;
- {
- char abuf[26];
-
- sprintf( abuf, TIMEFORM, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min );
- return( abuf );
- }
-
- phone_stat( phone )
- char *phone;
-
- /* Figure out the phone line status. There are five possible states:
- Idle - completely free line
- Ansr - getty
- Mach - incoming machine
- User - incoming user
- Call - outbound
-
- These five states are defined roughly as follows:
-
- Ansr - utmp -> LOGIN_PROCESS.
- Mach - utmp -> USER_PROCESS; E LCK.
- User - utmp -> USER_PROCESS; ~E LCK.
- Call - utmp -> nothing; E LCK.
- Idle - utmp -> nothing; ~E LCK.
-
- Basically, we decide what we have by a process of elimination.
-
- Known bugs: This may have problems with HDB UUCP, since I've got no
- way to test against it. One thing that I am sure of is that since I
- believe that uugetty creates a LCK..device file, this routine will
- consistently mistake users logged in through uugetty for machines
- logged into uucico. */
-
- {
- struct utmp ut_try, *ut, *getutline();
- short utmptype;
- char machine[MACHLEN];
-
- /* Look for the phone line in the utmp file. getutline() should return
- only LOGIN_PROCESS, USER_PROCESS, or NULL (for failure). We need to
- save some values before the endutent() call because it clears out the
- static structure pointed to by the return value of getutline(). We
- save the ut_user field because uucico creates a machine LCK file using
- the first six characters of this name. */
-
- strcpy( ut_try.ut_line, phone );
- ut = getutline( &ut_try );
- utmptype = ut->ut_type;
- strcpy( machine, ut->ut_user );
-
- /* AT&T UUCP specifies a maximum length of six characters. Remove this
- line for less brain-damaged implementations. */
-
- machine[6] = '\0';
- endutent();
-
- /* First condition: was there a utmp entry? */
-
- if ( ut != NULL )
-
- /* There was. If the type field is LOGIN_PROCESS, we have a getty and can
- return the appropriate value and quit. */
-
- if ( utmptype == LOGIN_PROCESS )
- return( ANSR );
- else
-
- /* A USER_PROCESS is incoming and can be either a user or a uucico. An
- incoming uucico has a LCK..machine file, so we check for that. */
-
- return( locked( machine ) ? MACH : USER );
- else
-
- /* There is no utmp entry. There are only two possibilities here; if there
- is an outgoing call of some sort, there will be a LCK..device file; if
- not, the line is really idle. */
-
- return( locked( phone ) ? CALL : IDLE );
-
- /* Shouldn't reach here. */
-
- }
-
- locked( device )
- char *device;
-
- /* See if a lock file exists. */
-
- {
- char temp[MAXPATHLEN];
- int fd;
-
- /* Make up the full path name. */
-
- strcpy( temp, LOCKDIR );
- strcat( temp, LOCKPREFIX );
- strcat( temp, device );
-
- /* Attempt to open the lock file. Assume that if the open fails the lock
- file does not exist. */
-
- fd = open( temp, O_RDONLY );
- if ( fd == -1 )
- return( FALSE );
- close( fd );
- return( TRUE );
- }
-
- curwinno()
-
- /* Figure out the current window; we need a starting point, after all.
- Known bug: this sometimes returns the wrong value if it gets into a
- race condition with a terminating/restarting (eg, getty) job. It also
- doesn't check to see if the ioctl fails. */
-
- {
- int foowin, dummy, temp;
-
- foowin = open( "/dev/window", O_RDONLY );
- temp = ioctl( foowin, WIOCGCURR, dummy );
- close( foowin );
- return( temp );
- }
-
- wcheckz()
-
- /* This is where the code to check for change-window keys lives. Also,
- sleep for the main program here. It should return about every TICK
- seconds. */
-
- {
- int tock, newwin, dir;
-
- tock = 0;
-
- do {
- /* Check for a command key. */
-
- if ( ( dir = checkey() ) != NOWHERE ) {
-
- /* Determine which window is next and select it. */
-
- if ( dir != HERE ) {
- newwin = nexwin( curwinno(), dir );
- ioctl( newwin, WIOCSELECT );
- close( newwin );
- }
- tock = TICK; /* Kludge to force return and redisplay. */
- }
- }
-
- /* Return after TICK tocks. */
-
- while ( tock++ < TICK );
- }
-
- justgoon()
-
- /* Stub routine to "handle" the alarm signal. Doesn't do a lot. */
-
- {
- return;
- }
-
- checkey()
-
- /* Check and see if one of our keys has been poked. The only keys this window
- is supposed to respond to all generate three character escape sequences.
- Set and catch an alarm signal to keep from getting hung in the fread();
- this probably could be done more neatly some other way, but... */
-
- {
- int direction, i;
- FILE *fw;
- char key[3];
-
- /* Set the alarm signal. */
-
- signal( SIGALRM, justgoon );
- alarm( 1 );
- if ( fread( key, 1, 3, stdin ) == 3 ) {
-
- /* Reset the alarm signal to be ignored. */
-
- signal( SIGALRM, SIG_IGN );
- alarm( 0 );
-
- /* Pick a function. */
-
- switch ( key[2] ) {
- case 'C' : showprocs(); direction=HERE; break;
- case 'D' : showutmp(); direction=HERE; break;
- case 'E' : showdir( LOCKDIR, LOCKPREFIX ); direction=HERE; break;
- case 'F' : showdir( MAILDIR, "" ); direction=HERE; break;
- case 'G' : showfsys(); direction=HERE; break;
- case 'H' : showdir( LOCKDIR, COMPREFIX ); direction=HERE; break;
- case 'I' : showdir( LOCKDIR, UUXPREFIX ); direction=HERE; break;
- case 'J' : showdir( LOCKDIR, "" ); direction=HERE; break;
- case 'p' :
- case 'P' : direction = FORWARD; break;
- case 'q' :
- case 'Q' : direction = BACKWARD; break;
- case 'Z' : help(); direction = HERE; break;
- default : direction = NOWHERE; break;
- }
- }
- else
- direction = NOWHERE;
-
- /* Reset the alarm signal to be ignored. */
-
- signal( SIGALRM, SIG_IGN );
- alarm( 0 );
- return( direction );
- }
-
- nexwin( winno, dir )
- int winno, dir;
-
- /* Decide what should be the next window. This relies on the fact that
- when you open a window device directly the open call will fail if it has
- not already been opened by someone else; this is how we find the open
- windows. Invisible windows should have their user-text set to "Invisible"
- if they wish to be ignored. */
-
- {
- int wd;
- char windex[12];
- struct utdata wintext;
-
- /* Trivial loop; at worst, we'll wind up back where we started. I suppose
- it's possible to have a system with no windows except those marked as
- "Invisible"; it doesn't seem too useful, though. */
-
- while ( 1 ) {
-
- /* Forward/backward sort-of modulo arithmetic. Real modulo arithmetic
- starts at zero. */
-
- winno += ( dir == FORWARD ? 1 : -1 );
- if ( winno > MAXWIN )
- winno = MINWIN;
- else if ( winno < MINWIN )
- winno = MAXWIN;
-
- /* Generate a window name and test for existence. */
- sprintf( windex, "/dev/w%d", winno );
- if ( ( wd = open( windex, O_RDONLY ) ) != -1 ) {
-
- /* It exists, now look at its user text info. This is where "Invisible"
- gets skipped. */
-
- wintext.ut_num = WTXTUSER;
- ioctl( wd, WIOCGETTEXT, &wintext );
- if ( strcmp( wintext.ut_text, "Invisible" ) )
- return( wd );
- else
- close( wd );
- }
- }
- }
-
- showprocs()
-
- /* Find the process table; run through it, looking up the user areas and
- printing out some data on each one on the fly. Works like 'ps -ef'
- command. */
-
- {
- struct proc *ppt;
- static struct nlist sym[3] = { { "tuhi", }, { "proc", }, { (char *)0, }, };
- struct tunable tune;
- int mem, kmem;
- FILE *wp;
-
- signal( SIGALRM, justgoon );
-
- /* Open up a window; also open the memory devices for reading. */
-
- wp = fopen( "/dev/window", "w" );
- mem = open( "/dev/mem", O_RDONLY );
- kmem = open( "/dev/kmem", O_RDONLY );
-
- /* Find the tunable parameters, to get the maximum number of processes; and
- the process table. */
-
- nlist( "/unix", sym );
- dmemcopy( kmem, (char *)&tune, (long)(sym[0].n_value), (long)sizeof( tune ) );
- dmemcopy( kmem, (char *)&ppt, (long)(sym[1].n_value), (long)sizeof( ppt ) );
-
- /* Run through the process table. */
-
- fprintf( wp, "REAL UID EFECT ID PID PPID START TIME TTY COMMAND\n" );
- while ( tune.nproc-- )
- printproc( wp, kmem, mem, ppt++ );
-
- /* Empty the output buffer, sleep to allow it to be read, and close up the
- extra window and return. */
-
- fflush( wp );
- sleep( WHOSLEEP );
- fclose( wp );
- signal( SIGALRM, SIG_IGN );
- }
-
- showutmp()
-
- /* Run through the utmp file. Used to give an idea of system activity. */
-
- {
- struct utmp *ut, *getutent();
- FILE *wp;
-
- signal( SIGALRM, justgoon );
- wp = fopen( "/dev/window", "w" );
-
- /* Go through utmp. Show login and user processes. */
-
- while ( ( ut = getutent() ) != NULL ) {
- switch ( (int) ut->ut_type ) {
- case USER_PROCESS :
- case LOGIN_PROCESS : showutent( wp, ut );
- default : break;
- }
- }
- endutent();
- fprintf( wp, "\n" );
- fflush( wp );
- sleep( WHOSLEEP );
- fclose( wp );
- signal( SIGALRM, SIG_IGN );
- }
-
- showdir( dirname, mask )
- char *dirname, *mask;
-
- /* Display the contents of a directory. Use 'mask' to specify a file prefix
- string to look for; useful for finding 'LCK..' files. */
-
- {
- DIR *dirp;
- struct directy *dir;
- FILE *wp;
- int mlen;
-
- signal( SIGALRM, justgoon );
- wp = fopen( "/dev/window", "w" );
- dirp = opendir( dirname );
- mlen = strlen( mask );
- while ( ( dir = readdir( dirp ) ) != NULL ) {
- if ( ( dir->d_name[0] != '.' ) && ( !strncmp( dir->d_name, mask, mlen ) ) ){
- fprintf( wp, "\n%s%s", dirname, dir->d_name );
- }
- }
- closedir( dirp );
- fprintf( wp, "\n" );
- fflush( wp );
- sleep( WHOSLEEP );
- fclose( wp );
- signal( SIGALRM, SIG_IGN );
- }
-
- showfsys()
-
- /* Show the root file system statistics. Read the superblock in and get
- free blocks, total blocks, and free inodes from it. Also display the
- freespace as a percentage. */
-
- {
- int rp;
- struct filsys fs;
-
- signal( SIGALRM, justgoon );
- rp = open( "/dev/rfp002", O_RDONLY );
- lseek( rp, 512, 0 );
- read( rp, &fs, sizeof( fs ) );
- close( rp );
- printf( "\nRoot: %ldK free %ldK total %d%% free %d inodes", fs.s_tfree,
- fs.s_fsize, (int)(100.0*(float)(fs.s_tfree)/(float)(fs.s_fsize)),
- fs.s_tinode );
- fflush( stdout );
- sleep( 5 );
- printf( "\n" );
- signal( SIGALRM, SIG_IGN );
- }
-
- help()
-
- /* Print a help message on key usage. */
-
- {
- FILE *wp;
-
- signal( SIGALRM, justgoon );
- wp = fopen( "/dev/window", "w" );
- fprintf( wp, "\t- Phone line states\n\t\to Idle - completely free line\n" );
- fprintf( wp, "\t\to Ansr - computer answering line (getty job)\n" );
- fprintf( wp, "\t\to Mach - incoming machine\n\t\to User - incoming user\n" );
- fprintf( wp, "\t\to Call - any outbound\n\t- Boot date and time\n" );
- fprintf( wp, "\t- Current run level\n\t- Current date and time\n\t- Number of users\n" );
- fprintf( wp, "\tWhen Suspend is hit, it makes the next window current; Resume\n" );
- fprintf( wp, "\tmakes the last window current.\n\n" );
- fprintf( wp, "\tThe following functions are mapped to the function keys:\n" );
- fprintf( wp, "\tShift-F1: process display, similar to 'ps -ef'\n" );
- fprintf( wp, "\tShift-F2: utmp display, like 'who'\n" );
- fprintf( wp, "\tShift-F3: lists UUCP LCK.. files, if any\n" );
- fprintf( wp, "\tShift-F4: directory of /usr/mail\n" );
- fprintf( wp, "\tShift-F5: Root filesystem freespace and free inodes\n" );
- fprintf( wp, "\tShift-F6: lists UUCP C. files, if any\n" );
- fprintf( wp, "\tShift-F7: lists UUCP X. files, if any\n" );
- fprintf( wp, "\tShift-F8: directory of /usr/spool/uucp\n" );
- fprintf( wp, "\tShift-Print: display this list" );
- fflush( wp );
- sleep( WHOSLEEP );
- fclose( wp );
- signal( SIGALRM, SIG_IGN );
- }
-
- dmemcopy( devmem, buf, memloc, nbytes )
- int devmem;
- char *buf;
- long memloc, nbytes;
-
- /* Read from a memory device into a local buffer. */
-
- {
- lseek( devmem, memloc, 0 );
- read( devmem, buf, (unsigned)nbytes );
- }
-
- printproc( wp, kmem, mem, ppt )
- FILE *wp;
- int kmem, mem;
- struct proc *ppt;
-
- /* Get a process table entry and print some of the information from it. */
-
- {
- struct proc p;
- struct user u;
- struct passwd *pwd, *getpwuid();
- char curtime[26], ptty[7], *getptty();
-
- dmemcopy( kmem, (char *)&p, (long)ppt, (long)sizeof( struct proc ) );
- if ( p.p_flag & SLOAD ) {
- dmemcopy( mem, (char *)&u, (long)( ctob( p.p_addr[0] )+U_OFFSET ),
- (long)sizeof( struct user ) );
- pwd = getpwuid( p.p_uid );
- fprintf( wp, "%8s ", pwd->pw_name );
- pwd = getpwuid( p.p_suid );
- fprintf( wp, "%8s %5d %5d ", pwd->pw_name, p.p_pid, p.p_ppid );
- strcpy( curtime, fmttime( localtime( &u.u_start ) ) );
- strcpy( ptty, getptty( u.u_ttyd ) );
- fprintf( wp, "%11s %6s %s\n", curtime, ptty, u.u_comm );
- fflush( wp );
- }
- }
-
- char *getptty( devno )
- dev_t devno;
-
- /* Go from a device number to a device name. */
-
- {
- DIR *dirp;
- struct directy *dir;
- struct stat sbuf;
- char name[14];
- static char tname[7];
-
- strcpy( tname, "none" );
- if ( !devno )
- return( tname );
- dirp = opendir( DEVDIR );
- while ( ( dir = readdir( dirp ) ) != NULL ) {
- if ( dir->d_name[0] != '.' ) {
- strcpy( name, DEVDIR );
- strcat( name, dir->d_name );
- stat( name, &sbuf );
- if ( devno == sbuf.st_rdev ) {
- closedir( dirp );
- strcpy( tname, dir->d_name );
- return( tname );
- }
- }
- }
- closedir( dirp );
- return( tname );
- }
-
- showutent( fp, u )
- FILE *fp;
- struct utmp *u;
-
- /* Print a formatted utmp entry. */
-
- {
- char curtime[26], *fmttime();
-
- strcpy( curtime, fmttime( localtime( &( u->ut_time ) ) ) );
- fprintf( fp, "%8s %14s %11s %5d\n", u->ut_user, u->ut_line, curtime, u->ut_pid );
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'startmgr.c'
- then
- echo shar: will not over-write existing file "'startmgr.c'"
- else
- cat << \SHAR_EOF > 'startmgr.c'
- /* startmgr: Create a one-line window on the top line of the Unix-PC
- (7300/3B1) screen and start a program running in that window.
- Declare this window to be the Window Manager, which gives it control
- over the Suspend, Resume and Print keys. This is meant to be used to
- start newmgr, but can probably be adapted to be a fairly generic program
- starter. It was designed to mimic the observed operation of things like
- cron, smgr, etc.
-
- This software is Copyright (c) 1987 by Scott Hazen Mueller.
-
- Permission is hereby granted to copy, reproduce, redistribute or
- otherwise use this software as long as: there is no monetary
- profit gained specifically from the use or reproduction or this
- software, it is not sold, rented, traded or otherwise marketed, and
- this copyright notice is included prominently in any copy
- made.
-
- The author make no claims as to the fitness or correctness of
- this software for any use whatsoever, and it is provided as is.
- Any use of this software is at the user's own risk.
-
- (Copyright notice courtesy of News 2.11 :-)
-
- Additionally: you break it, you bought it. I've listed the problems
- that I know of in comments in the code; if you come up with fixes, I'd
- like to see them, but I'm not planning on supporting anything. It's
- "good enough"; that's all that I'm looking for. */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <wind.h>
- #include <sys/window.h>
- #include <fcntl.h>
- #include <termio.h>
-
- /* Parameters defining the window and the program for that window. You'll
- almost certainly have to change barprog to correspond with whatever
- directory you use for your local stuff.
-
- Note: WFLAGS was determined empirically, by looking at the flags for
- the AT&T-supplied smgr window. No guarantees here. */
-
- #define BARPROG "/usr/local/newmgr"
- #define WXSTART 0
- #define WYSTART 0
- #define WWIDTH 720
- #define WHEIGHT 12
- #define WFLAGS 257
-
- main()
- {
- int wd, dummy;
- struct uwdata winbar;
- struct utdata winname;
- struct termio bartty;
-
- winbar.uw_x = WXSTART;
- winbar.uw_y = WYSTART;
- winbar.uw_width = WWIDTH;
- winbar.uw_height = WHEIGHT;
- winbar.uw_uflags = WFLAGS;
- winname.ut_num = WTXTUSER;
-
- strcpy( winname.ut_text, "Invisible" );
- if ( fork() )
- exit( 0 );
- else {
-
- /* Setpgrp() cannot be called from processes associated with windows.
- From the manual. Since it's a cleaner model for the parent to redirect
- the child's stdin, stdout and stderr, we do that. We have to setpgrp(),
- or else the child would be killed when the process group leader exited. */
-
- fclose( stdin );
- fclose( stdout );
- fclose( stderr );
- setpgrp();
-
- /* Get a window, and set it up according to our parameters. Since stdin
- was closed above, wd gets to be stdin (roughly). */
-
- wd = open( "/dev/window", O_RDWR|O_EXCL, 0 );
- ioctl( wd, WIOCSETD, &winbar );
- ioctl( wd, WIOCSETTEXT, &winname );
- ioctl( wd, WIOCSYS, SYSWMGR );
- ioctl( wd, WIOCSYS, SYSPMGR );
-
- /* Set up the child's stdout and stderr to point at the window. */
-
- dup( wd );
- dup( wd );
-
- /* Set terminal parameters; after all, we'll want to read escape codes and
- other neat stuff. */
-
- ioctl( wd, TCGETA, &bartty );
- bartty.c_iflag &= ~IGNBRK;
- bartty.c_lflag &= ~( ICANON | ECHO );
-
- /* Read three characters at a time; 1 second timeout interval. Whether
- this really does anything, I don't know. */
-
- bartty.c_cc[4] = 3;
- bartty.c_cc[5] = 10;
- ioctl( wd, TCSETA, &bartty );
-
- /* Execute with no command line arguments. */
-
- execl( BARPROG, BARPROG, 0 );
- }
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'ndir.c'
- then
- echo shar: will not over-write existing file "'ndir.c'"
- else
- cat << \SHAR_EOF > 'ndir.c'
- #if !defined(BSD4_2) && !defined(BSD4_1C) && !defined(HP9K5)
- #ifdef M_XENIX
- #include <sys/types.h>
- #endif /* M_XENIX */
- #include <sys/param.h>
- #include "ndir.h"
-
- #ifdef SCCSID
- static char *SccsId = "@(#)ndir.c 1.12 10/15/87";
- #endif /* SCCSID */
-
- /*
- * support for Berkeley directory reading routine on a V7 file system
- */
-
- extern char *malloc();
-
- /*
- * open a directory.
- */
- DIR *
- opendir(name)
- char *name;
- {
- register DIR *dirp;
- register int fd;
-
- if ((fd = open(name, 0)) == -1)
- return NULL;
- if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
- close (fd);
- return NULL;
- }
- dirp->dd_fd = fd;
- dirp->dd_loc = 0;
- return dirp;
- }
-
- /*
- * read an old style directory entry and present it as a new one
- */
- #ifdef pyr
- /* Pyramid in the AT&T universe */
- #define ODIRSIZ 248
- struct olddirect {
- long od_ino;
- short od_fill1, od_fill2;
- char od_name[ODIRSIZ];
- };
- #else /* V7 file system */
- #define ODIRSIZ 14
-
- struct olddirect {
- short od_ino;
- char od_name[ODIRSIZ];
- };
- #endif /* !pyr */
-
- /*
- * get next entry in a directory.
- */
- struct directy *
- readdir(dirp)
- register DIR *dirp;
- {
- register struct olddirect *dp;
- static struct directy dir;
-
- for (;;) {
- if (dirp->dd_loc == 0) {
- dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
- DIRBLKSIZ);
- if (dirp->dd_size <= 0)
- return NULL;
- }
- if (dirp->dd_loc >= dirp->dd_size) {
- dirp->dd_loc = 0;
- continue;
- }
- dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
- dirp->dd_loc += sizeof(struct olddirect);
- if (dp->od_ino == 0)
- continue;
- dir.d_ino = dp->od_ino;
- strncpy(dir.d_name, dp->od_name, ODIRSIZ);
- dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
- dir.d_namlen = strlen(dir.d_name);
- dir.d_reclen = DIRSIZ(&dir);
- return (&dir);
- }
- }
-
- /*
- * close a directory.
- */
- void
- closedir(dirp)
- register DIR *dirp;
- {
- close(dirp->dd_fd);
- dirp->dd_fd = -1;
- dirp->dd_loc = 0;
- free((char *)dirp);
- }
-
- /*
- * seek to an entry in a directory.
- * Only values returned by "telldir" should be passed to seekdir.
- */
- void
- seekdir(dirp, loc)
- register DIR *dirp;
- long loc;
- {
- long curloc, base, offset;
- struct directy *dp;
- long lseek(), telldir();
-
- curloc = telldir(dirp);
- if (loc == curloc)
- return;
- base = loc & ~(DIRBLKSIZ - 1);
- offset = loc & (DIRBLKSIZ - 1);
- (void) lseek(dirp->dd_fd, base, 0);
- dirp->dd_loc = 0;
- while (dirp->dd_loc < offset) {
- dp = readdir(dirp);
- if (dp == NULL)
- return;
- }
- }
-
- /*
- * return a pointer into a directory
- */
- long
- telldir(dirp)
- DIR *dirp;
- {
- return lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc;
- }
- #endif /* !BSD4_2 && !BSD4_1C && !HP9K5 */
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'ndir.h'
- then
- echo shar: will not over-write existing file "'ndir.h'"
- else
- cat << \SHAR_EOF > 'ndir.h'
- /* @(#)ndir.h 1.7 10/7/87 */
- #if defined(HP9K5)
- /* He should have included it instead of this, but prevent confusion */
- #include <ndir.h>
- #else /* other */
- #ifndef DEV_BSIZE
- #define DEV_BSIZE 512
- #endif
- #define DIRBLKSIZ DEV_BSIZE
- #define MAXNAMLEN 255
-
- struct directy {
- long d_ino; /* inode number of entry */
- short d_reclen; /* length of this record */
- short d_namlen; /* length of string in d_name */
- char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
- };
-
- /*
- * The DIRSIZ macro gives the minimum record length which will hold
- * the directory entry. This requires the amount of space in struct directy
- * without the d_name field, plus enough space for the name with a terminating
- * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
- */
-
- #ifdef DIRSIZ
- #undef DIRSIZ
- #endif /* DIRSIZ */
- #define DIRSIZ(dp) \
- ((sizeof (struct directy) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
-
- /*
- * Definitions for library routines operating on directories.
- */
- typedef struct _dirdesc {
- int dd_fd;
- long dd_loc;
- long dd_size;
- char dd_buf[DIRBLKSIZ];
- } DIR;
- #ifndef NULL
- #define NULL 0
- #endif
- extern DIR *opendir();
- extern struct directy *readdir();
- extern void closedir();
-
- #define rewinddir(dirp) seekdir((dirp), (long)0)
- #endif /* other */
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
- --
- Scott Hazen Mueller uunet!zorch!scott scott@zorch.UU.NET
- (408) 245-9461
-